using System;
using System.IO;
using System.Text.RegularExpressions;
using MediaController.Client.DAL;

namespace MediaController.Extractor
{
    public class Archive : IComparable
    {
        #region Data Members

        private readonly DirectoryInfo _directory;
        private readonly FileInfo _file;
        private readonly Unrar _unrar = new Unrar();

        #endregion

        public Archive(FileSystemInfo directory, FileInfo file)
        {
            _directory = new DirectoryInfo(Path.GetFullPath(directory.FullName));
            _file = file;
        }

        public DirectoryInfo Directory
        {
            get { return _file.Directory; }
        }

        public FileInfo File
        {
            get { return _file; }
        }

        public Unrar Unrar
        {
            get { return _unrar; }
        }

        public bool Contains(FileInfo f)
        {
            string str;
            if (_file.Equals(f))
            {
                return true;
            }
            if (f.FullName.Length != _file.FullName.Length)
            {
                return false;
            }
            if (f.Directory != null && _file.Directory != null)
            {
                if (!f.Directory.FullName.Equals(_file.Directory.FullName))
                {
                    return false;
                }
            }

            if (((str = f.Extension) != null) && (str == ".rar"))
            {
                var regex = new Regex(@"^(.*)\.part([0-9]+)\.rar$", RegexOptions.IgnoreCase);
                Match match = regex.Match(f.Name);
                Match match2 = regex.Match(_file.Name);
                return ((((match != Match.Empty) && (match2 != Match.Empty)) &&
                         match.Groups[1].Value.Equals(match2.Groups[1].Value)) &&
                        (match.Groups[2].Value.Length == match2.Groups[2].Value.Length));
            }
            int length = (f.FullName.Length - f.Extension.Length) - 3;
            return f.FullName.Substring(0, length).Equals(_file.FullName.Substring(0, length));
        }

        /// <summary>
        /// Unpack the archive file to the archive directory
        /// </summary>
        public void Unpack()
        {
            Unpack(Directory.FullName);
        }

        /// <summary>
        ///  Unpack the archive file to the given directory
        /// <param name="path">directory to extract the archive in to</param>        
        /// </summary>
        public void Unpack(string path)
        {
            try
            {
                _unrar.DestinationPath = path;
                _unrar.Open(File.FullName, Unrar.OpenMode.Extract);
                while (_unrar.ReadHeader())
                {
                    try
                    {
                        _unrar.Extract();
                        continue;
                    }
                    catch
                    {

                        Logger.Log(string.Format("Error: {0}", "Write error in the file " + File.Name));
                        continue;
                    }
                }
            }
            catch (IOException ex)
            {
                throw new Exception("Error while " + ex.Message, ex);

            }
            catch (Exception ex)
            {
                Logger.Log(string.Format(ex.ToString()));
                throw new Exception("Error while unpacking: " + ex.Message, ex);
            }
            finally
            {
                if (_unrar != null)
                {
                    _unrar.Close();
                }
            }
        }

        public int CompareTo(object obj)
        {
            if (!(obj is Archive))
            {
                throw new ArgumentException("object is not an Archive");
            }
            var archive = (Archive)obj;
            return File.FullName.CompareTo(archive.File.FullName);
        }

        public override string ToString()
        {
            return _file.FullName.Substring(_directory.FullName.Length + 1);
        }
    }
}